package com.run_java_test.test_run;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;

@Component
class DynamicControllerManager {

    @Autowired
    private ApplicationContext applicationContext;

    public boolean addOrUpdateController(String sourceCodePath, String className) {
        String outputDir = "D:\\a2software_cache\\IDEAProject\\self\\java_study_springboot_run_java_source_code\\code_test\\";

        // Step 1: Compile the source code
        if (!compileSourceCode(sourceCodePath, outputDir)) {
            return false;
        }

        try {
            // Step 2: Load the class
            Class<?> dynamicClass = loadClass(outputDir, className);

            // Step 3: Register or replace the bean in the Spring context
            registerOrReplaceBean(applicationContext, className, dynamicClass);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean compileSourceCode(String sourceFilePath, String outputDir) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            throw new IllegalStateException("JavaCompiler is not available. Please ensure you are using a JDK.");
        }

        try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
            new File(outputDir).mkdirs(); // Ensure output directory exists

            // 修复选项：将 -d 和 outputDir 分开
            Iterable<String> options = Arrays.asList("-d", outputDir);
            Iterable<? extends File> sourceFiles = Collections.singletonList(new File(sourceFilePath));

            return compiler.getTask(null, fileManager, null, options, null, fileManager.getJavaFileObjectsFromFiles(sourceFiles)).call();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private Class<?> loadClass(String outputDir, String className) throws Exception {
        URL[] urls = {new File(outputDir).toURI().toURL()};
        try (URLClassLoader classLoader = new URLClassLoader(urls)) {
            return classLoader.loadClass(className);
        }
    }

    private void registerOrReplaceBean(ApplicationContext applicationContext, String beanName, Class<?> newBeanClass) {
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

        // 如果 bean 已存在，则删除旧的 bean 定义
//        if (beanFactory.containsBeanDefinition(beanName)) {
//            beanFactory.removeBeanDefinition(beanName);
//        }


        if (beanFactory.containsBeanDefinition(beanName)) {
            beanFactory.removeBeanDefinition(beanName);
            System.out.println("Replaced existing bean definition for: " + beanName);
        } else {
            System.out.println("Registering new bean definition for: " + beanName);
        }


        // 注册新的 bean 定义
//        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
//        beanDefinition.setBeanClass(newBeanClass);
//        beanFactory.registerBeanDefinition(beanName, beanDefinition);

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(newBeanClass);
        beanDefinition.setBeanClassName("dynamicController"); // 给 Bean 设置一个显式名称
        beanFactory.registerBeanDefinition("dynamicController", beanDefinition);
    }


//    private void registerOrReplaceBean(ApplicationContext applicationContext, String beanName, Class<?> newBeanClass) {
//        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
//        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
//
//        if (beanFactory.containsBeanDefinition(beanName)) {
//            // Remove the old bean definition
//            beanFactory.removeBeanDefinition(beanName);
//        }
//
//        // Register the new bean definition
//        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
//        beanDefinition.setBeanClass(newBeanClass);
//        beanFactory.registerBeanDefinition(beanName, beanDefinition);
//    }
}
